package util
{
	import util.*;
	
	public class Observable
	{
			  // A flag indicating whether this object has changed.
			 public  var changed:Boolean = false;
	 		 // A list of observers.
			 public  var observers:Array;


 			 /**
  			 * Constructor function.
   			*/
 			 public  function Observable () 
 			 {
  				  observers = new Array();
 			 }



 			 /**
  			 * Adds an observer to the list of observers.
  				 * @param   o   The observer to be added.
  			 */
 			public function addObserver(o:Observer):Boolean 
			 {
  			  // Can't add a null observer.
    			if (o == null) 
   				 {
    			  return false;
         		 }

    			// Don't add an observer more than once.
   			 	for (var i:Number = 0; i < observers.length; i++) 
    			{
    	  		if (observers[i] == o) 
    	 		 {
    	    	// The observer is already observing, so quit.
    	    	return false;
    	  		}
   	    	}

		    // Put the observer into the list.
		   		 observers.push(o);
		   		 return true;
		 }

  
  
 		 /**
  		 * Removes an observer from the list of observers.
  		 *
 		  * @param   o   The observer to remove.
  			 */
 		  public function removeObserver(o:Observer):Boolean 
 		 {
  		  // Find and remove the observer.
  				  var len:Number = observers.length;
  			  for (var i:Number = 0; i < len; i++) 
  			  {
      			if (observers[i] == o) 
      			{
      		  	observers.splice(i, 1);
        		return true;
      			}
      		  }
  
   		 return false;
 		 }

  
  
  
			  /**
			   * Tell all observers that the subject has changed.
			   *
			   * @param   infoObj   An object containing arbitrary data 
			   *                    to pass to observers.
			   */
			  public  function notifyObservers(infoObj:Object):void
			  {
				    // Use a null infoObject if none is supplied.
				    trace("Inside notifyObserver class :)");
			    	if (infoObj == undefined) 
			    	{
			    	  infoObj = null;
			    	}
			
			   	 // If the object hasn't changed, don't bother notifying observers.
			   	 	if (!changed) 
			   	 	{
			     	 return;
			    	}
			
			    		// Make a copy of the observers array. We do this
			   		    // so that we can be sure the list won't change while
			  		    // we're processing it.
			  	  var observersSnapshot:Array = observers.slice(0);
			
			    // This change has been processed, so unset the "changed" flag.
			    clearChanged();
			trace("No. of observers = "+this.observers.length);
			    // Invoke update() on all observers.
			    for (var i:Number = observersSnapshot.length-1; i >= 0; i--) 
			    	{
			    	  observersSnapshot[i].update(this, infoObj);
			    	}
			  }

  
  
  
  
			  /**
			   * Removes all observers from the observer list.
			   */
			 public function clearObservers():void 
			  {
			    observers = new Array();
			  }
  
  

			  /**
			   * Indicates that the subject has changed.
			   */
			  public function setChanged():void 
			  {
			    trace("telling the observable class that there is a change :)");
			    changed = true;
			  }

			  /**
			   * Indicates that the subject has either not changed or
			   * has notified its observers of the most recent change.
			   */
			  public function clearChanged():void 
			  {
			    changed = false;
			  }

			  /**
			   * Checks if the subject has changed.
			   *
			   * @return   true if the subject has changed, as determined by setChanged().
			   */
			  public function hasChanged():Boolean 
			  {
			    return changed;
			  }

  
  
		  /**
		   * Returns the number of observers in the observer list.
		   *
		   * @return   An integer: the number of observers for this subject.
		   */
  			 public function countObservers():Number 
 			 {
  			  return observers.length;
  			}
		}

	}
